/*
 * BRAIN10.h
 */

/* prevents multiple definitions in header files */
#ifndef _BRAIN
#define _BRAIN

// BRAIN10 Physical Machine
typedef struct
{
    /* 0 - 999 are for Processes
     * 1000 - 1099 is shared storage
     * 8000 - 8999 are for instructions
     * 9000 - 9999 is for data
     */ 
    char storage[10000][4]; // storage 0 - 9999
    char R[4];              // general purpose register
    char SP[4];             // stack pointer
    int C;                  // toggle boolean
    int IC;                 // instruction counter
    int SPindx;             // stack pointer index
    int numProcesses;       // number of processes
    int currentProcess;     // active process ID
    int dataLine;
    int BR;                 // Counter for Base Registers
    int PLB[100][10];       // Master Page Table
    
    /*
     * Ready Queue variables
     */
    int readyQueue[100];
    int in;
    int out;
} BRAIN10;


// BRAIN10 Virtual Machines
typedef struct
{
    char vStorage[10][100][4];  // VM storage
    char vR[20][4];             // VM general purpose register
    char vSP[20][4];            // VM stack pointer
    int vC[20];                 // VM toggle boolean
    int vIC[20];                // VM instruction counter
    int vSPIndex[20];           // VM stack pointer index
    int BR[20];                 // VM base registers
    int LR[20];                 // VM limit registers
    int pID[20];                // VM process IDs
    int PF[20];                 // VP number of page frames required.
} VBRAIN10;

// Assign values to BRAIN variables
void initiateBrain(BRAIN10 *brain10);


// Assign values to VBRAIN variables
void initializeVBrain(VBRAIN10 *vbrain10);

/* 
 * Occupy storage words with BRAIN file operations
 * input:
 *   - storage word number 0-99 [x1x2]
 *   - pointer to BRAIN10 struct 
 */
void allocateMemory(char instruction[], BRAIN10 *brain10, VBRAIN10 *vbrain10);


/* 
 * Executes the input instruction using an
 * absolutely atrocious nested conditional.
 */
void executeInstruction(int process, char instruction[], BRAIN10 *brain10, VBRAIN10 *vbrain10, MAILMAN *mailman, SEMAPHORES *semaphores);

/*
 * Push a process onto the semaphore wait queue.
 */
void pushReadyProcess(BRAIN10 *brain10, int process);

/*
 * Pop the last process off the semaphore wait queue,
 * allowing them to access shared storage on the next
 * time slice.
 */
int popReadyProcess(BRAIN10 *brain10);

#endif
